import cv2
import json
import numpy

from PIL import Image
from pathlib import Path


class WeChat:
    def __init__(self):
        self.image = None
        self.objs = []

    def decode(self, image):
        self.image = image.convert("RGBA")
        self.objs = []

        BASE_DIR = Path(__file__).parent

        detector = cv2.wechat_qrcode_WeChatQRCode(
            BASE_DIR.joinpath("model/detect.prototxt").as_posix(),
            BASE_DIR.joinpath("model/detect.caffemodel").as_posix(),
            BASE_DIR.joinpath("model/sr.prototxt").as_posix(),
            BASE_DIR.joinpath("model/sr.caffemodel").as_posix(),
        )

        results, points = detector.detectAndDecode(
            cv2.cvtColor(numpy.asarray(image), cv2.COLOR_RGB2BGR)
        )

        for index, result in enumerate(results):
            self.objs.append(self.parse_result(result, points[index]))

        return self.objs

    def parse_result(self, result, points):
        try:
            data = json.loads(result)
        except BaseException:
            data = result

        obj = {
            "format": "QR_CODE",
            "type": "TEXT",
            "data": data,
            "points": [],
            "background": None,
        }

        for point in points:
            obj["points"].append((point[0], point[1]))

        if obj.get("points"):
            obj["background"] = self.image.getpixel(obj.get("points")[0])

        return obj

    def crop(self, obj):
        points = obj.get("points")

        if not points:
            return None

        if len(points) >= 4:
            x = None
            y = None
            x2 = None
            y2 = None

            for point in points:
                if x is None:
                    x = point[0]
                else:
                    x = min(point[0], x)

                if y is None:
                    y = point[1]
                else:
                    y = min(point[1], y)

                if x2 is None:
                    x2 = point[0]
                else:
                    x2 = max(point[0], x2)

                if y2 is None:
                    y2 = point[1]
                else:
                    y2 = max(point[1], y2)

            try:
                return self.image.crop((x, y, x2, y2))
            except BaseException:
                pass

        return None
